<?php
// +----------------------------------------------------------------------
// | 汇潮支付
// +----------------------------------------------------------------------

namespace helper\payment\ecpss;

use GuzzleHttp\Client;
use helper\payment\ecpss\request\ScanMerchantConfRequest;
use helper\payment\ecpss\request\ScanMerchantInQueryRequest;
use helper\payment\ecpss\request\ScanMerchantInRequest;
use helper\payment\ecpss\request\ScanPayRequest;
use helper\util\Random;
use helper\util\Encrypt;
use helper\util\StringBuilder;

class Ecpss
{
    private array $config;

    private Client $client;

    public function __construct(array $config)
    {
        $this->config = [
            'merNo' => $config['merNo'] ?? "",
            'privateKey' => $config['privateKey'] ?? "",
            'publicKey' => $config['publicKey'] ?? "",
            'channelNo' => $config['channelNo'] ?? ""
        ];
        $this->client = new Client(['base_uri' => 'https://gwapi.yemadai.com/', 'timeout' => 30]);
    }

    /**
     * 渠道商户入驻
     */
    public function applyMerchant()
    {
        //组装请求信息
        $dto = new ScanMerchantInRequest();
        $dto->setMerNo($this->config['merNo']);
        $dto->setVersion("1.0");
        $dto->setPayType("WXZF_ONLINE");            //支付类型
        $dto->setRandomStr(Random::nextString(12));  //最大为32位
        $dto->setChannelNo($this->config['channelNo']);     //入驻支付方式所对应的渠道号
        $dto->setMerName("安徽火讯网络科技有限公司");  //要求与营业执照上的名称一致，如为个体、无营业执照的，则填写为：个体户***（如个体户张三）
        $dto->setShortName("火讯网络");            //商户简称
        $dto->setServicePhone("0552-30366616"); //客服电话
        $dto->setBusiness("545");                  //行业类别
        $dto->setProvince("安徽省");
        $dto->setCity("蚌埠市");
        $dto->setDistrict("蚌山区");
        $dto->setAddress("安徽省蚌埠市蚌山区凤凰国际B座10层10");
        $dto->setCardNo("187261857905");
        $dto->setCardName("中国银行股份有限公司蚌埠长征路支行");
        $dto->setBusinessLicense("91340303MA8LA5J0XW");
        $dto->setBusinessLicenseType("NATIONAL_LEGAL");
        $dto->setSubAppID("wx72a8eda27cba7b36");
        $dto->setPayPath("pages/pay/pay");
        $dto->setSignInfo($this->makeSignForMerchantIn($dto->getMerNo(),$dto->getPayType(),$dto->getRandomStr()));
        
        //构造xml，并base64
        $xml = new StringBuilder();
        $xml->append("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>");
        $xml->append("<ScanMerchantInRequest>");
        $xml->append("<MerNo>")->append($dto->getMerNo())->append("</MerNo>");
        $xml->append("<Version>")->append($dto->getVersion())->append("</Version>");
        $xml->append("<PayType>")->append($dto->getPayType())->append("</PayType>");
        $xml->append("<SignInfo>")->append($dto->getSignInfo())->append("</SignInfo>");
        $xml->append("<RandomStr>")->append($dto->getRandomStr())->append("</RandomStr>");
        $xml->append("<ChannelNo>")->append($dto->getChannelNo())->append("</ChannelNo>");
        $xml->append("<MerchantInfo>");
        $xml->append("<MerName>")->append($dto->getMerName())->append("</MerName>");
        $xml->append("<ShortName>")->append($dto->getShortName())->append("</ShortName>");
        $xml->append("<ServicePhone>")->append($dto->getServicePhone())->append("</ServicePhone>");
        $xml->append("<Business>")->append($dto->getBusiness())->append("</Business>");
        $xml->append("<City>")->append($dto->getCity())->append("</City>");
        $xml->append("<District>")->append($dto->getDistrict())->append("</District>");
        $xml->append("<Address>")->append($dto->getAddress())->append("</Address>");
        $xml->append("<Province>")->append($dto->getProvince())->append("</Province>");
        $xml->append("<CardNo>")->append($dto->getCardNo())->append("</CardNo>");
        $xml->append("<CardName>")->append($dto->getCardName())->append("</CardName>");
        $xml->append("<BusinessLicense>")->append($dto->getBusinessLicense())->append("</BusinessLicense>");
        $xml->append("<BusinessLicenseType>")->append($dto->getBusinessLicenseType())->append("</BusinessLicenseType>");
        $xml->append("<SubAppID>")->append($dto->getSubAppID())->append("</SubAppID>");
        $xml->append("<PayPath>")->append($dto->getPayPath())->append("</PayPath>");
        $xml->append("</MerchantInfo>");
        $xml->append("</ScanMerchantInRequest>");
        $str = base64_encode($xml->toString());

        //发送请求信息
        return $this->sendData('scanpay/merchantIn', $str);
    }

    /**
     * 渠道商户入驻查询
     * @return string
     */
    public function merchantInQuery(): string
    {
        //组装请求信息
        $dto = new ScanMerchantInQueryRequest();
        $dto->setMerNo($this->config['merNo']);
        $dto->setPayType("WXZF_ONLINE");
        $dto->setCompanyNo("sweep-cc068278685b43b69878044c795795db");
        $dto->setRandomStr(Random::nextString(12));
        $dto->setVersion("1.0");
        $dto->setSignInfo($this->makeSignForQueryMerchantIn($dto->getMerNo(), $dto->getPayType(), $dto->getCompanyNo(), $dto->getRandomStr()));

        //构造xml，并base64
        $xml = new StringBuilder();
        $xml->append("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>");
        $xml->append("<ScanMerchantInQueryRequest>");
        $xml->append("<MerNo>")->append($dto->getMerNo())->append("</MerNo>");
        $xml->append("<Version>")->append($dto->getVersion())->append("</Version>");
        $xml->append("<PayType>")->append($dto->getPayType())->append("</PayType>");
        $xml->append("<SignInfo>")->append($dto->getSignInfo())->append("</SignInfo>");
        $xml->append("<RandomStr>")->append($dto->getRandomStr())->append("</RandomStr>");
        $xml->append("<CompanyNo>")->append($dto->getCompanyNo())->append("</CompanyNo>");
        $xml->append("</ScanMerchantInQueryRequest>");
        $str = base64_encode($xml->toString());

        echo $str;
        echo '<br/>';

        //发送请求信息
        return $this->sendData('scanpay/merchantInQuery', $str);
    }

    /**
     * 渠道商户入驻修改
     */
    public function merchantUpdate()
    {
        //组装请求信息
        $dto = new ScanMerchantInRequest();
        $dto->setMerNo("46082");
        $dto->setVersion("1.0");
        $dto->setPayType("ZFBZF");
        $dto->setRandomStr(Random::nextString(12));
        $dto->setChannelNo("2088431913653104");
        $dto->setMerName("");
        $dto->setShortName("");
        $dto->setContactName("");
        $dto->setServicePhone("");
        $dto->setBusiness("2015050700000000");
        $dto->setMcc("5812");
        $dto->setContactTag("06");
        $dto->setContactType("CONTROLLER");
        $dto->setCity("上海市");
        $dto->setDistrict("普陀区");
        $dto->setAddress("长风新村街道");
        $dto->setProvince("上海市");
        $dto->setCardNo("");
        $dto->setCardName("");
        $dto->setCompanyNo("sweep-8320d2c7d9494b41908707acf016b743");
        $dto->setSignInfo($this->makeSignForMerchantUpdate($dto->getCompanyNo(),$dto->getMerNo(),$dto->getPayType(),$dto->getRandomStr()));

        //构造xml，并base64
        $xml = new StringBuilder();
        $xml->append("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>");
        $xml->append("<ScanMerchantInRequest>");
        $xml->append("<MerNo>")->append($dto->getMerNo())->append("</MerNo>");
        $xml->append("<Version>")->append($dto->getVersion())->append("</Version>");
        $xml->append("<PayType>")->append($dto->getPayType())->append("</PayType>");
        $xml->append("<SignInfo>")->append($dto->getSignInfo())->append("</SignInfo>");
        $xml->append("<RandomStr>")->append($dto->getRandomStr())->append("</RandomStr>");
        $xml->append("<ChannelNo>")->append($dto->getChannelNo())->append("</ChannelNo>");
        $xml->append("<CompanyNo>")->append($dto->getCompanyNo())->append("</CompanyNo>");
        $xml->append("<MerchantInfo>");
        $xml->append("<MerName>")->append($dto->getMerName())->append("</MerName>");
        $xml->append("<ShortName>")->append($dto->getShortName())->append("</ShortName>");
        $xml->append("<ContactName>")->append($dto->getContactName())->append("</ContactName>");
        $xml->append("<ServicePhone>")->append($dto->getServicePhone())->append("</ServicePhone>");
        $xml->append("<Business>")->append($dto->getBusiness())->append("</Business>");
        $xml->append("<Mcc>")->append($dto->getMcc())->append("</Mcc>");
        $xml->append("<ContactTag>")->append($dto->getContactTag())->append("</ContactTag>");
        $xml->append("<ContactType>")->append($dto->getContactType())->append("</ContactType>");
        $xml->append("<City>")->append($dto->getCity())->append("</City>");
        $xml->append("<District>")->append($dto->getDistrict())->append("</District>");
        $xml->append("<Address>")->append($dto->getAddress())->append("</Address>");
        $xml->append("<Province>")->append($dto->getProvince())->append("</Province>");
        $xml->append("<CardNo>")->append($dto->getCardNo())->append("</CardNo>");
        $xml->append("<CardName>")->append($dto->getCardName())->append("</CardName>");
        $xml->append("</MerchantInfo>");
        $xml->append("</ScanMerchantInRequest>");
        $str = base64_encode($xml->toString());

        //发送请求信息
        return $this->sendData('scanpay/merchantUpdate', $str);
    }

    /**
     * 支付
     * @return string
     */
    public function scanPay()
    {
        //组装请求信息
        $dto = new ScanPayRequest();
        $dto->setMerNo("46082");
        $dto->setPayType("AliJsapiPay_OffLine");
        $dto->setAmount("0.01");
        $dto->setReturnUrl("www.baidu.com");
        $dto->setAdviceUrl("www.baidu.com");
        $dto->setScanpayMerchantCode("sweep-123456");
        $dto->setProducts("1");
        $dto->setRemark("2");

        //构造xml，并base64
        $xml = new StringBuilder();
        $xml->append("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>");
        $xml->append("<ScanPayRequest>");
        $xml->append("<MerNo>")->append($dto->getMerNo())->append("</MerNo>");
        $xml->append("<BillNo>")->append($dto->getBillNo())->append("</BillNo>");
        $xml->append("<payType>")->append($dto->getPayType())->append("</payType>");
        $xml->append("<Amount>")->append($dto->getAmount())->append("</Amount>");
        $xml->append("<OrderTime>")->append($dto->getOrderTime())->append("</OrderTime>");
        $xml->append("<ScanpayMerchantCode>")->append($dto->getScanpayMerchantCode())->append("</ScanpayMerchantCode>");
        $xml->append("<AdviceUrl>")->append($dto->getAdviceUrl())->append("</AdviceUrl>");
        $xml->append("<SignInfo>")->append($this->makeSignForScanPay($dto->getMerNo(), $dto->getBillNo(), $dto->getAmount(), $dto->getOrderTime(), $dto->getAdviceUrl()))->append("</SignInfo>");
        $xml->append("<products>")->append($dto->getProducts())->append("</products>");
        $xml->append("<remark>")->append($dto->getRemark())->append("</remark>");
        $xml->append("</ScanPayRequest>");
        $str = base64_encode($xml->toString());

        //发送请求信息
        return $this->sendData('pay/scanpay', $str);
    }

    /**
     * 聚合支付
     * @return void
     */
    public function aggregatePay()
    {

    }

    /**
     * 微信配置
     * @return string
     */
    public function subMerchantConf(): string
    {
        //组装请求信息
        $dto = new ScanMerchantConfRequest();
        $dto->setMerNo($this->config['merNo']);
        $dto->setCompanyNo("sweep-cc068278685b43b69878044c795795db");
        $dto->setVersion("1.0");
        $dto->setMethodName("CONF_QUERY");//SUBAPPID_CONF PAYPATH_CONF CONF_QUERY
        $dto->setSubAppid("wx72a8eda27cba7b36");//
        $dto->setPayPath("pages/pay/pay");//pages/pay/pay
        $dto->setRandomStr(Random::nextString(12));
        $dto->setSignInfo($this->makeSignForSubMerchantConf($dto->getMerNo(), $dto->getCompanyNo(), "", $dto->getRandomStr()));
        // "&SubAppid" . $dto->getSubAppid() ; "&PayPath" . $dto->getPayPath() ; ""

        //构造xml，并base64
        $xml = new StringBuilder();
        $xml->append("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>");
        $xml->append("<ScanMerchantConfRequest>");
        $xml->append("<MerNo>")->append($dto->getMerNo())->append("</MerNo>");
        $xml->append("<CompanyNo>")->append($dto->getCompanyNo())->append("</CompanyNo>");
        $xml->append("<Version>")->append($dto->getVersion())->append("</Version>");
        $xml->append("<RandomStr>")->append($dto->getRandomStr())->append("</RandomStr>");
        $xml->append("<SignInfo>")->append($dto->getSignInfo())->append("</SignInfo>");
        $xml->append("<MethodName>")->append($dto->getMethodName())->append("</MethodName>");
        $xml->append("<SubAppid>")->append($dto->getSubAppid())->append("</SubAppid>");
        $xml->append("<PayPath>")->append($dto->getPayPath())->append("</PayPath>");
        $xml->append("</ScanMerchantConfRequest>");
        $str = base64_encode($xml->toString());

        echo $str;

        //发送请求信息
        return $this->sendData('scanpay/subMerchantConf', $str, false);
    }

    private function makeSignForMerchantIn(String $merNo, String $payType, String $randomStr): string
    {
        $plain = "MerNo=" . $merNo . "&" . "PayType=" . $payType . "&" . "RandomStr=" . $randomStr;
        return Encrypt::sha1WithRSASign($plain, $this->config['privateKey']);
    }

    private function makeSignForQueryMerchantIn(string $merNo, string $payType, string $companyNo, string $randomStr): string
    {
        $plain = "MerNo=" . $merNo . "&" . "CompanyNo=" . $companyNo . "&" . "PayType=" . $payType . "&" . "RandomStr=" . $randomStr;
        return Encrypt::sha1WithRSASign($plain, $this->config['privateKey']);
    }

    private function makeSignForMerchantUpdate(String $companyNo, String $merNo, String $payType, String $randomStr): string
    {
        $plain = "CompanyNo=" . $companyNo . "&" . "MerNo=" . $merNo . "&" . "PayType=" . $payType . "&" . "RandomStr=" . $randomStr;
        return Encrypt::sha1WithRSASign($plain, $this->config['privateKey']);
    }

    public function makeSignForScanPay(String $merNo, String $billNo,  String $amount, String $orderTime, String $adviceUrl): string
    {
        $plain = "MerNo=" . $merNo . "&" . "BillNo=" . $billNo . "&" . "Amount=" . $amount . "&" . "OrderTime=" . $orderTime . "&" . "AdviceUrl=" . $adviceUrl;
        return Encrypt::sha1WithRSASign($plain, $this->config['privateKey']);
    }

    public function makeSignForSubMerchantConf(String $companyNo, String $merNo, String $sing, String $randomStr): string
    {
        $plain = "CompanyNo=" . $companyNo . "&" . "MerNo=" . $merNo . $sing . "&" . "RandomStr=" . $randomStr;
        return Encrypt::sha1WithRSASign($plain, $this->config['privateKey']);
    }

    private function sendData(string $url, string $data, bool $isBase64 = true)
    {
        $response = $this->client->request('POST', $url . '?requestDomain=' . $data);
        if ($response->getStatusCode() == 200) {
            $body = $response->getBody();
            return $isBase64 ? base64_decode($body) : $body;
        }
        return '';
    }
}